Skip to content

chore(dashboard): fix bugs found in dashboard review - #135

Merged
TimVosch merged 9 commits into
mainfrom
chore/dashboard-review-fixes
Sep 1, 2026
Merged

chore(dashboard): fix bugs found in dashboard review#135
TimVosch merged 9 commits into
mainfrom
chore/dashboard-review-fixes

Conversation

@TimVosch

@TimVosch TimVosch commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Fixes a batch of bugs found during a review of the dashboard web app. Each fix was developed in an isolated worktree and merged together; the combined branch builds, vets, and is gofmt-clean.

Fixes

Critical

  • Pipeline "Create" page crash — the traces panel dereferenced p.Pipeline.Id unconditionally; on /pipelines/create Pipeline is nil, panicking mid-render. The panel is now guarded with {% if p.Pipeline != nil %}. (views/pipelineEditPage.qtpl)

High

  • Device list pagination dropped the sensor-group filtercreateSensorGroup/deleteSensorGroup passed a bare cursor where a URL was expected (breaking infinite scroll), and getDevicesTable/deviceListPage omitted sensor_group from the next-page URL (page 2+ returned all devices). All four spots now build full …?sensor_group=&cursor= URLs (delete correctly omits the filter). (routes/overview.go)
  • Datastream websocket missing returns — bad start/end params wrote an HTTP error then still tried to upgrade the socket on a committed response. Added return after each parse error. (routes/overview.go)

Medium

  • updatePipeline error handling — read resp.Body when resp could be nil, fell through to a nil-deref status check, and had an unreachable errors.As branch. Rewritten to be nil-safe and return after surfacing the error. Superseded by the shared error helper in the review follow-up below. (routes/pipelines.go)
  • Trace timeline panictrace.WorkerTimes[j] could index out of range when the API returns fewer times than workers. Added a bounds guard. (routes/ingress.go)
  • Worker description couldn't be cleared — empty form values were skipped; description is now sent whenever the form contains the field (refined in the review follow-up below). (routes/workers.go)
  • Create-worker ignored the Enabled togglecreateWorker now reads state and sets it. (routes/workers.go)

Low / robustness

  • Added middleware.Recoverer so handler/template panics return a clean 500 instead of dropping the connection. (main.go)
  • Fixed formatSince copy ("About 1 hour ago" / "About 1 minute ago") and removed a duplicated branch. (routes/ingress.go)
  • Closed websocket frame writers per-iteration instead of defer-ing in a loop. (routes/overview.go)
  • Removed stray fmt.Print* debug statements. (workers.go, pipelines.go, main.go)

Review follow-ups (4249155)

A second review pass on this branch surfaced seven more findings, all fixed:

  • Pipeline create/update failures now surface the API's error — new shared handleAPIClientError helper unwraps api.GenericOpenAPIError, shows the API's message in the snackbar, and writes a real error status (previously update fell through to a generic snackbar with HTTP 200, so htmx treated failed saves as successful; create returned a raw HTTP error). The unreachable errors.As(*web.APIError) branch and the dead StatusCode != StatusCreated block are removed. (routes/pipelines.go)
  • updateWorker description PATCH semantics — the field is only sent when present in the form (presence check via r.Form), so an omitted key no longer erases the stored description while an explicitly emptied textarea still clears it, matching the server's nil=keep / ""=clear contract. (routes/workers.go)
  • CSRF rejections are logged again — the nosurf failure handler bypasses the chi logger, so it now logs nosurf.Reason with method and path, and returns 400 instead of a silent 200. (main.go)
  • Deduplicated next-page URL construction — one devicesTableNextPage(next, sensorGroupID) helper replaces four inline copies that sourced sensor_group three different ways. (routes/overview.go)
  • Deduplicated worker state mappingformState(r) replaces the duplicated checkbox switch in createWorker/updateWorker. (routes/workers.go)
  • formatSince pluralization — extracted an about(n, unit) helper; "About 1 second ago" now renders correctly and negative durations from clock skew clamp to zero. (routes/ingress.go)

Verification

go build ./services/dashboard/..., go vet ./services/dashboard/..., and gofmt -l all clean.

Not included (cosmetic / larger calls)

Worker name field styled to look disabled but editable; empty 200 on non-HTMX table endpoints; external CDN dependencies; unescaped server data in inline <script> strings; dead Trace.PipelineName.

🤖 Generated with Claude Code

TimVosch and others added 9 commits June 15, 2026 10:25
The traces panel on the pipeline editor dereferenced p.Pipeline.Id unconditionally, panicking when rendering the create page (Pipeline is nil). Hide the panel when there is no pipeline yet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… prints

Avoid nil resp.Body deref, return after surfacing an error instead of falling through to a nil-deref status check, and remove stray fmt.Printf debug output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e copy

Avoid an out-of-range panic when WorkerTimes is shorter than Workers, and fix the duplicated/ungrammatical hour branches in formatSince.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… fix datastream ws error handling

Build full next-page URLs (with sensor_group when filtered) instead of bare cursors; add missing returns after start/end parse errors in the datastream websocket; close per-frame websocket writers instead of deferring in a loop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add middleware.Recoverer so handler/template panics return a clean 500 instead of dropping the connection, and remove a stray nosurf reason debug print.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…le on create, drop debug prints

Always send the worker description so it can be cleared, set state from the Enabled checkbox when creating a worker, and remove stray fmt.Println debug output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Combines six independent fixes from the dashboard review:
- guard pipeline create page against nil Pipeline (panic)
- preserve sensor_group in device pagination + datastream ws returns
- correct pipeline update error handling + drop debug prints
- guard trace worker-time indexing + fix relative-time copy
- allow clearing worker description, honor enabled toggle on create
- add panic recovery middleware + drop debug print

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tion

- surface API error messages and real status codes for pipeline create/update
  via a shared handleAPIClientError helper; remove dead error branches
- only send worker description when present in the form so an omitted field
  no longer erases the stored description
- log nosurf CSRF rejections with reason and return 400 instead of silent 200
- deduplicate device-table next-page URL construction into one helper
- deduplicate worker state checkbox mapping into formState
- fix 'About 1 seconds ago' pluralization and clamp negative durations

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UyNzyujudsPcubHodWnzp9
@TimVosch
TimVosch merged commit 7308ec1 into main Sep 1, 2026
2 of 3 checks passed
@TimVosch
TimVosch deleted the chore/dashboard-review-fixes branch September 1, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant